/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */

#include "../Thread.h"
#include <win32/win32.h>
#include <math/utl.h>

namespace liba
{
namespace threads
{

class Thread::Impl
{
public:
	Impl()
		:	handle( 0 )
	{}
    HANDLE handle;
	// this function is to access protected thread->run()
	static void run(Thread * thread)
	{
		thread->run();
	}
};

Thread::Thread()
:	impl( new Impl() ),
	processID( 0 ),
	need_termination_flag( false )
{}

Thread::~Thread()
{
	if( impl->handle )
	{
		CloseHandle(impl->handle); impl->handle = 0;
	}
	delete impl; impl = 0;
}

static unsigned long WINAPI ThreadProc(void * thread_pointer)
{
    Thread * thread = reinterpret_cast<Thread *>(thread_pointer);
	
	Thread::Impl::run( thread );
    return 0;
}

bool Thread::start()
{
	if( impl->handle ) 
		return false;

	impl->handle = CreateThread(0, 0, ThreadProc, this, 0, &processID );
    
	return impl->handle != 0;
}

void Thread::wait_termination()
{
	if( impl->handle )
	{
		WaitForSingleObject( impl->handle, INFINITE );
		CloseHandle(impl->handle); impl->handle = 0;
	}
}

void Thread::request_termination()
{
	need_termination_flag = true;
}

bool Thread::need_termination()volatile const
{
	return need_termination_flag;
}

bool Thread::set_priority( int priority )
{
	static int table[] = 
	{
		THREAD_PRIORITY_LOWEST,
		THREAD_PRIORITY_BELOW_NORMAL,
		THREAD_PRIORITY_NORMAL,
		THREAD_PRIORITY_ABOVE_NORMAL,
		THREAD_PRIORITY_HIGHEST
	};
	return SetThreadPriority( impl->handle, table[ 2 + math::clamp(priority, -2, 2) ] ) != 0;
}

void Thread::resume()
{
	ResumeThread( impl->handle );
}

void Thread::suspend()
{
	SuspendThread( impl->handle );
}

} // namespace threads
} //namespace liba